#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
机器学习常用模型实战 - 线性回归、逻辑回归、决策树
重点：理解三种核心模型原理和应用场景
"""

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
from sklearn.datasets import make_regression, make_classification, load_iris
from sklearn.metrics import mean_squared_error, accuracy_score, classification_report, confusion_matrix
from sklearn.preprocessing import StandardScaler
import seaborn as sns

plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False

print("🤖 机器学习常用模型实战开始")
print("=" * 60)

# 1. 线性回归模型
print("1. 线性回归模型 (Linear Regression)")
print("-" * 40)

# 生成回归数据
X_reg, y_reg = make_regression(n_samples=200, n_features=1, noise=10, random_state=42)

# 划分训练集和测试集
X_train_reg, X_test_reg, y_train_reg, y_test_reg = train_test_split(
    X_reg, y_reg, test_size=0.2, random_state=42
)

# 创建线性回归模型
lr_model = LinearRegression()

# 训练模型
lr_model.fit(X_train_reg, y_train_reg)

# 预测
lr_predictions = lr_model.predict(X_test_reg)

# 评估模型
mse = mean_squared_error(y_test_reg, lr_predictions)
r2_score = lr_model.score(X_test_reg, y_test_reg)

print(f"线性回归模型性能:")
print(f"均方误差 (MSE): {mse:.2f}")
print(f"R² 分数: {r2_score:.2f}")
print(f"模型参数: 斜率 = {lr_model.coef_[0]:.2f}, 截距 = {lr_model.intercept_:.2f}")

# 2. 逻辑回归模型
print("\n2. 逻辑回归模型 (Logistic Regression)")
print("-" * 40)

# 生成分类数据
X_clf, y_clf = make_classification(n_samples=200, n_features=2, n_redundant=0, 
                                   n_informative=2, n_clusters_per_class=1, 
                                   random_state=42)

# 划分训练集和测试集
X_train_clf, X_test_clf, y_train_clf, y_test_clf = train_test_split(
    X_clf, y_clf, test_size=0.2, random_state=42
)

# 数据标准化
scaler = StandardScaler()
X_train_clf_scaled = scaler.fit_transform(X_train_clf)
X_test_clf_scaled = scaler.transform(X_test_clf)

# 创建逻辑回归模型
logreg_model = LogisticRegression(random_state=42)

# 训练模型
logreg_model.fit(X_train_clf_scaled, y_train_clf)

# 预测
logreg_predictions = logreg_model.predict(X_test_clf_scaled)
logreg_proba = logreg_model.predict_proba(X_test_clf_scaled)

# 评估模型
accuracy = accuracy_score(y_test_clf, logreg_predictions)

print(f"逻辑回归模型性能:")
print(f"准确率: {accuracy:.2f}")
print(f"模型参数: 系数 = {logreg_model.coef_}, 截距 = {logreg_model.intercept_}")

# 3. 决策树模型
print("\n3. 决策树模型 (Decision Tree)")
print("-" * 40)

# 使用鸢尾花数据集
iris = load_iris()
X_iris, y_iris = iris.data, iris.target

# 划分训练集和测试集
X_train_iris, X_test_iris, y_train_iris, y_test_iris = train_test_split(
    X_iris, y_iris, test_size=0.2, random_state=42
)

# 创建决策树分类器
dt_model = DecisionTreeClassifier(max_depth=3, random_state=42)

# 训练模型
dt_model.fit(X_train_iris, y_train_iris)

# 预测
dt_predictions = dt_model.predict(X_test_iris)

# 评估模型
dt_accuracy = accuracy_score(y_test_iris, dt_predictions)

print(f"决策树模型性能:")
print(f"准确率: {dt_accuracy:.2f}")
print(f"分类报告:")
print(classification_report(y_test_iris, dt_predictions, target_names=iris.target_names))

# 4. 模型对比与可视化
print("\n4. 模型对比与可视化")
print("-" * 40)

fig = plt.figure(figsize=(15, 10))

# 子图1: 线性回归可视化
plt.subplot(2, 3, 1)
plt.scatter(X_train_reg, y_train_reg, alpha=0.7, label='训练数据')
plt.scatter(X_test_reg, y_test_reg, alpha=0.7, color='red', label='测试数据')

# 绘制回归线
x_line = np.linspace(X_reg.min(), X_reg.max(), 100).reshape(-1, 1)
y_line = lr_model.predict(x_line)
plt.plot(x_line, y_line, 'black', linewidth=2, label='回归线')

plt.xlabel('特征值')
plt.ylabel('目标值')
plt.title('线性回归模型')
plt.legend()
plt.grid(True)

# 子图2: 逻辑回归决策边界
plt.subplot(2, 3, 2)
xx, yy = np.meshgrid(np.linspace(-3, 3, 100), np.linspace(-3, 3, 100))
Z = logreg_model.predict_proba(np.c_[xx.ravel(), yy.ravel()])[:, 1]
Z = Z.reshape(xx.shape)

plt.contourf(xx, yy, Z, alpha=0.8, cmap=plt.cm.RdBu)
plt.scatter(X_train_clf_scaled[:, 0], X_train_clf_scaled[:, 1], c=y_train_clf, 
           cmap=plt.cm.RdBu, edgecolors='black')
plt.xlabel('特征1')
plt.ylabel('特征2')
plt.title('逻辑回归决策边界')

# 子图3: 决策树分类结果
plt.subplot(2, 3, 3)
cm = confusion_matrix(y_test_iris, dt_predictions)
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', 
           xticklabels=iris.target_names, yticklabels=iris.target_names)
plt.xlabel('预测标签')
plt.ylabel('真实标签')
plt.title('决策树混淆矩阵')

# 子图4: 模型性能对比
plt.subplot(2, 3, 4)
models = ['线性回归', '逻辑回归', '决策树']
performance = [r2_score, accuracy, dt_accuracy]
colors = ['skyblue', 'lightgreen', 'lightcoral']

bars = plt.bar(models, performance, color=colors, alpha=0.8)
plt.ylim(0, 1)
plt.ylabel('性能指标')
plt.title('模型性能对比')

# 在柱状图上添加数值标签
for bar, value in zip(bars, performance):
    plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.01, 
             f'{value:.2f}', ha='center', va='bottom')

# 子图5: 特征重要性（决策树）
plt.subplot(2, 3, 5)
feature_importance = dt_model.feature_importances_
features = iris.feature_names

plt.barh(range(len(features)), feature_importance, color='lightblue')
plt.yticks(range(len(features)), features)
plt.xlabel('特征重要性')
plt.title('决策树特征重要性')

# 子图6: 学习曲线示例
plt.subplot(2, 3, 6)
# 模拟不同训练集大小下的性能变化
train_sizes = np.linspace(0.1, 0.9, 9)
train_scores = []
test_scores = []

for size in train_sizes:
    X_train_temp, _, y_train_temp, _ = train_test_split(
        X_iris, y_iris, train_size=size, random_state=42
    )
    
    dt_temp = DecisionTreeClassifier(max_depth=3, random_state=42)
    dt_temp.fit(X_train_temp, y_train_temp)
    
    train_scores.append(dt_temp.score(X_train_temp, y_train_temp))
    test_scores.append(dt_temp.score(X_test_iris, y_test_iris))

plt.plot(train_sizes, train_scores, 'o-', label='训练集准确率')
plt.plot(train_sizes, test_scores, 's-', label='测试集准确率')
plt.xlabel('训练集比例')
plt.ylabel('准确率')
plt.title('学习曲线')
plt.legend()
plt.grid(True)

plt.tight_layout()
plt.savefig('model_comparison.png', dpi=300, bbox_inches='tight')
plt.show()

# 5. 模型应用场景分析
print("\n5. 模型应用场景分析")
print("-" * 40)

print("📊 线性回归应用场景:")
print("- 房价预测、销量预测、趋势分析")
print("- 特点：连续值预测，简单易解释")
print("- 优势：计算效率高，可解释性强")
print("- 局限：假设线性关系，对异常值敏感")

print("\n🔍 逻辑回归应用场景:")
print("- 信用评分、用户流失预测、疾病诊断")
print("- 特点：二分类或多分类问题")
print("- 优势：输出概率值，可解释性强")
print("- 局限：需要线性可分数据")

print("\n🌳 决策树应用场景:")
print("- 客户细分、风险评估、医疗诊断")
print("- 特点：非参数模型，可处理非线性关系")
print("- 优势：可视化强，无需特征缩放")
print("- 局限：容易过拟合，对数据敏感")

# 6. 实战练习
print("\n6. 实战练习")
print("-" * 40)

print("练习1: 房价预测模型")
print("使用线性回归预测房价，考虑以下特征：")
print("- 房屋面积、卧室数量、地理位置")
print("- 评估模型性能，分析特征重要性")

print("\n练习2: 信用卡欺诈检测")
print("使用逻辑回归检测信用卡欺诈：")
print("- 特征：交易金额、时间、商户类型")
print("- 评估模型：准确率、召回率、F1分数")

print("\n练习3: 客户流失预测")
print("使用决策树预测客户流失：")
print("- 特征：使用时长、消费频率、投诉次数")
print("- 分析：哪些特征最重要？如何改进模型？")

# 7. 模型选择指南
print("\n7. 模型选择指南")
print("-" * 40)

print("🎯 问题类型决定模型选择:")
print("1. 回归问题 → 线性回归、决策树回归")
print("2. 分类问题 → 逻辑回归、决策树分类")
print("3. 复杂模式 → 随机森林、梯度提升")

print("\n🔧 模型选择考虑因素:")
print("- 数据量大小")
print("- 特征数量和类型")
print("- 模型可解释性要求")
print("- 计算资源限制")

print("\n💡 实用建议:")
print("- 从简单模型开始（线性回归/逻辑回归）")
print("- 如果性能不足，再尝试复杂模型")
print("- 始终进行交叉验证")
print("- 关注模型的可解释性")

print("\n" + "=" * 60)
print("🎯 学习要点总结:")
print("1. 理解三种核心模型的原理和应用场景")
print("2. 掌握模型训练、预测和评估的全流程")
print("3. 学会选择合适的模型解决实际问题")
print("4. 重点：模型性能评估和特征重要性分析")

print("\n下一步学习:")
print("- 模型评估指标深入理解")
print("- Scikit-learn高级功能")
print("- 第一个实战项目：泰坦尼克生存预测")

print("\n📚 推荐资源:")
print("- Scikit-learn官方文档")
print("- 《Python机器学习实战》")
print("- Kaggle入门竞赛")

print("\n🚀 运行建议:")
print("python 常用模型实战.py")
print("观察6个子图的可视化结果，理解不同模型的特点")